home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / Fab Libraries / Utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-03  |  32.1 KB  |  1,237 lines  |  [TEXT/MPS ]

  1. /*
  2. Copyright © 1993,1994 by Fabrizio Oddone
  3. ••• ••• ••• ••• ••• ••• ••• ••• ••• •••
  4. This source code is distributed as freeware: you can copy, exchange, modify this
  5. code as you wish. You may include this code in any kind of application: freeware,
  6. shareware, or commercial, provided that full credits are given.
  7. You may not sell or distribute this code for profit.
  8. */
  9.  
  10. #pragma load "MacDump"
  11.  
  12. #include    "Utils.h"
  13.  
  14. #pragma segment Main
  15.  
  16. static OSErr AskForDestFile(StdFileResultPtr whichFile);
  17.  
  18. /* AddSTRRes2Doc: adds the standard 'STR ' resource
  19. to a newly saved document */
  20.  
  21. OSErr AddSTRRes2Doc(FSSpec *theDoc, OSType myFcrea, OSType myFtype, short STRid, ScriptCode lScript)
  22. {
  23. register Handle    msgString;
  24. register short    fRefn;
  25. register OSErr    err;
  26.  
  27. DetachResource(msgString = (Handle)GetString(STRid));
  28. FSpCreateResFile(theDoc, myFcrea, myFtype, lScript);
  29. if ((err = ResError()) == noErr)
  30.     if ((fRefn = FSpOpenResFile(theDoc, fsRdWrPerm)) == -1)
  31.         err = ResError();
  32.     else {
  33.         AddResource(msgString, 'STR ', STRid, "\p");
  34.         if ((err = ResError()) == noErr) {
  35.             SetResAttrs(msgString, GetResAttrs(msgString) | resPurgeable);
  36.             err = ResError();
  37.             }
  38.         else
  39.             DisposHandle(msgString);
  40.         CloseResFile(fRefn);
  41.         }
  42. return err;
  43. }
  44.  
  45. /* AddSTRHand2Doc: adds the standard 'STR ' resource
  46. to a newly saved document */
  47.  
  48. OSErr AddSTRHand2Doc(FSSpec *theDoc, OSType myFcrea, OSType myFtype, StringHandle msgString, ScriptCode lScript)
  49. {
  50. register short    fRefn;
  51. register OSErr    err;
  52.  
  53. FSpCreateResFile(theDoc, myFcrea, myFtype, lScript);
  54. if ((err = ResError()) == noErr)
  55.     if ((fRefn = FSpOpenResFile(theDoc, fsRdWrPerm)) == -1)
  56.         err = ResError();
  57.     else {
  58.         AddResource(msgString, 'STR ', kSTR_ApplicationName, "\p");
  59.         if ((err = ResError()) == noErr) {
  60.             SetResAttrs(msgString, GetResAttrs(msgString) | resPurgeable);
  61.             err = ResError();
  62.             }
  63.         else
  64.             DisposHandle(msgString);
  65.         CloseResFile(fRefn);
  66.         }
  67. return err;
  68. }
  69.  
  70. OSErr AddRes2Doc(FSSpec *theDoc, Handle thisHandle, ResType rType, short rID)
  71. {
  72. register Handle    existHandle;
  73. register short    fRefn;
  74. register OSErr    err;
  75.  
  76. if ((fRefn = FSpOpenResFile(theDoc, fsRdWrPerm)) == -1)
  77.     err = ResError();
  78. else {
  79. //    if (noErr == (err = HandToHand(&thisHandle)))
  80.     existHandle = Get1Resource(rType, rID);
  81.     if (existHandle)
  82.         RmveResource(existHandle);
  83.     AddResource(thisHandle, rType, rID, "\p");
  84.     if ((err = ResError()) == noErr) {
  85.         SetResAttrs(thisHandle, GetResAttrs(thisHandle) | resPurgeable);
  86.         err = ResError();
  87.         }
  88.     CloseResFile(fRefn);
  89.     }
  90. return err;
  91. }
  92.  
  93. /* SendmyAE: we send an Apple Event with the specified ID to ourselves */
  94.  
  95. void SendmyAE(AEEventClass myclass, AEEventID myAEvtID, IdleProcPtr IdleFunct, AESendMode theMode)
  96. {
  97. AppleEvent    myAEvent;
  98. AppleEvent    myAEReply;
  99. AEAddressDesc    targetAddress;
  100. ProcessSerialNumber myPSN = { 0, kCurrentProcess };
  101. register OSErr    err;
  102.  
  103. if ((err = AECreateDesc(typeProcessSerialNumber, (Ptr)&myPSN, sizeof(ProcessSerialNumber),
  104.     &targetAddress)) == noErr) {
  105.     if ((err = AECreateAppleEvent(myclass, myAEvtID, &targetAddress,
  106.         kAutoGenerateReturnID, kAnyTransactionID, &myAEvent)) == noErr) {
  107.         err = AESend(&myAEvent, &myAEReply, theMode,
  108.             kAENormalPriority, kNoTimeOut, IdleFunct, 0L);
  109.         (void)AEDisposeDesc(&myAEvent);
  110.         }
  111.     (void)AEDisposeDesc(&targetAddress);
  112.     }
  113. }
  114.  
  115. /* SendmyAEPShort: we send an Apple Event with the specified ID to ourselves */
  116.  
  117. void SendmyAEPShort(AEEventClass myclass, AEEventID myAEvtID, IdleProcPtr IdleFunct, AESendMode theMode, short theAlert)
  118. {
  119. AppleEvent    myAEvent;
  120. AppleEvent    myAEReply;
  121. AEAddressDesc    targetAddress;
  122. ProcessSerialNumber myPSN = { 0, kCurrentProcess };
  123. register OSErr    err;
  124.  
  125. if ((err = AECreateDesc(typeProcessSerialNumber, (Ptr)&myPSN, sizeof(ProcessSerialNumber),
  126.     &targetAddress)) == noErr) {
  127.     if ((err = AECreateAppleEvent(myclass, myAEvtID, &targetAddress,
  128.         kAutoGenerateReturnID, kAnyTransactionID, &myAEvent)) == noErr) {
  129.  
  130.         err = AEPutParamPtr(&myAEvent, keyDirectObject, typeShortInteger, (Ptr)&theAlert, sizeof(theAlert));
  131.         if (err == noErr)
  132.             err = AESend(&myAEvent, &myAEReply, theMode,
  133.                 kAENormalPriority, kNoTimeOut, IdleFunct, 0L);
  134.         (void)AEDisposeDesc(&myAEvent);
  135.         }
  136.     (void)AEDisposeDesc(&targetAddress);
  137.     }
  138. }
  139.  
  140. /* ZoomRectToRect: draws zooming gray rectangles from startingRect to endingRect
  141. in the current port; numofDivs is the density of rectangles in the interval */
  142.  
  143. void ZoomRectToRect(RectPtr startingRect, RectPtr endingRect, short numofDivs)
  144. {
  145. PenState    curPen;
  146. Rect    trailingRect = { 0, 0, 0, 0 };
  147. Rect    tempRect;
  148. Handle    rectStorH;
  149. short    mtop, mleft, mbottom, mright;
  150. register long    ttopleft, tbotright;
  151. register short *spntr;
  152. register long *lpntr;
  153. register short    i, j, tsh;
  154.  
  155. if (numofDivs < BITS(short)) {
  156.     if (rectStorH = NewHandleGeneral(numofDivs * sizeof(Rect))) {
  157.         GetPenState(&curPen);
  158.         PenPat(&qd.gray);
  159.         PenMode(patXor);
  160.         mtop = endingRect->top - startingRect->top;
  161.         mleft = endingRect->left - startingRect->left;
  162.         mbottom = endingRect->bottom - startingRect->bottom;
  163.         mright = endingRect->right - startingRect->right;
  164.         spntr = (short *)*rectStorH;
  165.         for (i = 1; i <= numofDivs; i++) {
  166.             *spntr++ = mtop >>= 1;
  167.             *spntr++ = mleft >>= 1;
  168.             *spntr++ = mbottom >>= 1;
  169.             *spntr++ = mright >>= 1;
  170.             }
  171.         HLock(rectStorH);
  172.         for (i = 1; i < (1 << numofDivs); i++) {
  173.             ttopleft = *(long *)startingRect;
  174.             tbotright = ((long *)startingRect)[1];
  175.             lpntr = (long *)*rectStorH;
  176.             tsh = i << (BITS(short) - numofDivs);
  177.             for (j = 1; j <= numofDivs; j++) {
  178.                 if (tsh < 0) {
  179.                     ttopleft += *lpntr++;
  180.                     tbotright += *lpntr++;
  181.                     }
  182.                 else
  183.                     lpntr += 2;
  184.                 tsh <<= 1;
  185.                 }
  186.             
  187.             *(long *)&tempRect = ttopleft;
  188.             ((long *)&tempRect)[1] = tbotright;
  189.             FrameRect(&tempRect);
  190.             FrameRect(&trailingRect);
  191.             trailingRect = tempRect;
  192.             }
  193.         FrameRect(&tempRect);
  194.         DisposHandle(rectStorH);
  195.         SetPenState(&curPen);
  196.         }
  197.     }
  198. }
  199.  
  200. /* NewHandleGeneral: makes a new handle in main or temporary memory, arguably
  201. in the more suitable heap zone */
  202.  
  203. Handle NewHandleGeneral(Size blockSize)
  204. {
  205. register Handle    myH;
  206. OSErr    err;
  207.  
  208. if (TempFreeMem() > FreeMem()) {
  209.     if ((myH = TempNewHandle(blockSize, &err)) == nil) {
  210.         ResrvMem(blockSize);
  211.         myH = NewHandle(blockSize);
  212.         }
  213.     }
  214. else {
  215.     ResrvMem(blockSize);
  216.     if ((myH = NewHandle(blockSize)) == nil)
  217.         myH = TempNewHandle(blockSize, &err);
  218.     }
  219. return(myH);
  220. }
  221.  
  222. /* Get1ResGeneral: like Get1Resource, but loads in main or temporary memory */
  223.  
  224. Handle Get1ResGeneral(ResType theType,short theID)
  225. {
  226. register Handle    emptyH, destH;
  227. register Size    myResSize;
  228.  
  229. SetResLoad(false);
  230. emptyH = Get1Resource(theType, theID);
  231. SetResLoad(true);
  232. destH = NewHandleGeneral(myResSize = SizeResource(emptyH));
  233. if (destH) {
  234.     HLock(destH);
  235.     ReadPartialResource(emptyH, 0L, *destH, myResSize);
  236.     HUnlock(destH);
  237.     }
  238. ReleaseResource(emptyH);
  239. return(destH);
  240. }
  241.  
  242. OSType FindFinderAtEaseProcess(ProcessSerialNumber *theProcess)
  243. {
  244. ProcessInfoRec infoRec;
  245. ProcessSerialNumber process = {0, kNoProcess};
  246. register OSType    retVal = '????';
  247.  
  248. infoRec.processInfoLength = sizeof(ProcessInfoRec);
  249. infoRec.processName = nil;
  250. infoRec.processAppSpec = nil;
  251.  
  252. while (GetNextProcess(&process) == noErr) {
  253.     if (noErr == (GetProcessInformation(&process, &infoRec))) {
  254.         if ((infoRec.processType == (unsigned long)'FNDR') &&
  255.             ((infoRec.processSignature == 'MACS') || (infoRec.processSignature == 'mfdr'))) {
  256.             
  257.             retVal = infoRec.processSignature;
  258.             *theProcess = process;
  259.             break;
  260.             }
  261.         }
  262.     }
  263. return retVal;
  264. }
  265.  
  266. OSType FindFinderProcess(void)
  267. {
  268. ProcessInfoRec infoRec;
  269. ProcessSerialNumber process = {0, kNoProcess};
  270. register OSType    retVal = '????';
  271.  
  272. infoRec.processInfoLength = sizeof(ProcessInfoRec);
  273. infoRec.processName = nil;
  274. infoRec.processAppSpec = nil;
  275.  
  276. while (GetNextProcess(&process) == noErr) {
  277.     if (noErr == (GetProcessInformation(&process, &infoRec))) {
  278.         if ((infoRec.processType == (unsigned long)'FNDR') &&
  279.             (infoRec.processSignature == 'MACS')) {
  280.             
  281.             retVal = infoRec.processSignature;
  282.             break;
  283.             }
  284.         }
  285.     }
  286. return retVal;
  287. }
  288.  
  289. /* SendShutdownToFinder: we tell the Finder (or At Ease) to Shutdown (!) */
  290.  
  291. OSErr SendShutdownToFinder(IdleProcPtr myIdleFunct, Boolean wantShutDown)
  292. {
  293. AppleEvent    myAEvent;
  294. AppleEvent    myAEReply;
  295. ProcessSerialNumber    process;
  296. AEAddressDesc    targetAddress;
  297. OSType    WantedCreator;
  298. register OSErr    err = errAEDescNotFound;
  299.  
  300. WantedCreator = FindFinderAtEaseProcess(&process);
  301. if ('????' != WantedCreator)
  302.     if ((err = AECreateDesc(typeApplSignature, (Ptr)&WantedCreator, sizeof(OSType),
  303.         &targetAddress)) == noErr) {
  304.         if ((err = AECreateAppleEvent(kAEFinderEvents, wantShutDown ? kAEShutDown : kAERestart , &targetAddress,
  305.             kAutoGenerateReturnID, kAnyTransactionID, &myAEvent)) == noErr) {
  306.             err = AESend(&myAEvent, &myAEReply, kAENoReply | kAEAlwaysInteract | kAECanSwitchLayer,
  307.                 kAENormalPriority, kNoTimeOut, myIdleFunct, nil);
  308.             (void)AEDisposeDesc(&myAEvent);
  309.             if (err == noErr)
  310.                 (void)SetFrontProcess(&process);
  311.             }
  312.         (void)AEDisposeDesc(&targetAddress);
  313.         }
  314. return err;
  315. }
  316.  
  317. short FabStopAlert(short alertID, ModalFilterProcPtr filterProc, IdleProcPtr IdleFunct)
  318. {
  319. SendmyAE(kCreat, kAEAlert, IdleFunct, kAENoReply | kAEAlwaysInteract);
  320. InitCursor();
  321. return StopAlert(alertID, filterProc);
  322. }
  323.  
  324. short FabCautionAlert(short alertID, ModalFilterProcPtr filterProc, IdleProcPtr IdleFunct)
  325. {
  326. SendmyAE(kCreat, kAEAlert, IdleFunct, kAENoReply | kAEAlwaysInteract);
  327. InitCursor();
  328. return CautionAlert(alertID, filterProc);
  329. }
  330.  
  331. short FabNoteAlert(short alertID, ModalFilterProcPtr filterProc, IdleProcPtr IdleFunct)
  332. {
  333. SendmyAE(kCreat, kAEAlert, IdleFunct, kAENoReply | kAEAlwaysInteract);
  334. InitCursor();
  335. return NoteAlert(alertID, filterProc);
  336. }
  337.  
  338. short FabAlert(short alertID, ModalFilterProcPtr filterProc, IdleProcPtr IdleFunct)
  339. {
  340. SendmyAE(kCreat, kAEAlert, IdleFunct, kAENoReply | kAEAlwaysInteract);
  341. InitCursor();
  342. return Alert(alertID, filterProc);
  343. }
  344.  
  345. /* my Dialog box manager */
  346.  
  347. void FlashButton(DialogPtr dlg, short item)
  348. {
  349. Rect    txtBox;
  350. ControlHandle    itH;
  351. short    typ;
  352.  
  353. GetDItem(dlg, item, &typ, &(Handle)itH, &txtBox);
  354. HiliteControl(itH, 1);
  355. (void) MyDelay(4L);
  356. HiliteControl(itH, 0);
  357. }
  358.  
  359. void OutlineButton(DialogPtr oftheDialog, short myItem)
  360. {
  361. enum {
  362. kButtonFrameSize = 3,    /* button frameUs pen size */
  363. kButtonFrameInset = -4    /* inset rectangle adjustment around button */
  364. };
  365.  
  366. PenState    curPen;
  367. GrafPtr    savePort;
  368. Rect    txtBox;
  369. Handle    itH;
  370. short    typ;
  371.  
  372. GetPort(&savePort);
  373. SetPort(oftheDialog);
  374. GetDItem(oftheDialog, myItem, &typ, &itH, &txtBox);
  375. GetPenState(&curPen);
  376. PenNormal();
  377. InsetRect(&txtBox, kButtonFrameInset, kButtonFrameInset);
  378. typ = ((txtBox.bottom - txtBox.top) >> 1) + 2;
  379. if ((*(ControlHandle)itH)->contrlHilite == 0)
  380.     PenPat(&qd.black);
  381. else
  382.     PenPat(&qd.gray);
  383. PenSize(kButtonFrameSize, kButtonFrameSize);
  384. FrameRoundRect(&txtBox, typ, typ);
  385. SetPenState(&curPen);
  386. SetPort(savePort);
  387. }
  388.  
  389. short HandleDialog(ModalFilterProcPtr filterProc,
  390.                     dialogItemsPtr things,
  391.                     void (*initProc)(DialogPtr),
  392.                     void (*userProc)(DialogPtr, Handle, short),
  393.                     short resId)
  394. {
  395. Rect    box;
  396. Handle    item;
  397. GrafPtr    port;
  398. register long    myRefCon;
  399. register DialogPtr    dPtr;
  400. register dialogItemsPtr    spanPtr;
  401. dialogItemsPtr    itemToBeActivated;
  402. short    type, theItemHit;
  403. short    theGroup;
  404. register short    theType, iNum;
  405. register Boolean    editTextExists = false;
  406. Boolean    dialoging;
  407. #if !defined(FabSystem7orlater)
  408. long    Gresp;
  409. Boolean    dialogManager7Present = false;
  410. #endif
  411.  
  412. InitCursor();
  413. dPtr = GetNewDialog(resId, nil, (DialogPtr)-1L);
  414. if (dPtr) {
  415.     GetPort(&port);
  416.     SetPort(dPtr);
  417.  
  418. #if !defined(FabSystem7orlater)
  419.     if (Gestalt(gestaltDITLExtAttr, &Gresp) == noErr)
  420.         if (Gresp & (1L << gestaltDITLExtPresent))
  421.             dialogManager7Present = true;
  422. #endif
  423.  
  424. #pragma mark Setup
  425.     
  426.     spanPtr = things;
  427.     while (iNum = spanPtr->itemNumber) {
  428.         myRefCon = spanPtr->refCon;
  429.         GetDItem(dPtr, iNum, &type, &item, &box);
  430.         theType = type & itemDisable ? type - itemDisable : type;
  431.         switch(theType) {
  432.             case ctrlItem+btnCtrl:
  433. #if !defined(FabSystem7orlater)
  434.                 if (dialogManager7Present)
  435. #endif
  436.                     {
  437.                     if (myRefCon)
  438.                         (void) SetDialogDefaultItem(dPtr, iNum);
  439.                     if (iNum == cancel)
  440.                         (void) SetDialogCancelItem(dPtr, iNum);
  441.                     }
  442.                 break;
  443.             case ctrlItem+chkCtrl:
  444.             case ctrlItem+radCtrl:
  445.                 if (myRefCon > 0)
  446.                     SetCtlValue((ControlHandle)item, 1);
  447.                 else if (myRefCon < 0)
  448.                     HiliteControl((ControlHandle)item, 255);
  449.                 if (userProc)
  450.                     userProc(dPtr, item, iNum);
  451.                 break;
  452.             case ctrlItem+resCtrl:
  453.                 if (myRefCon)
  454.                     SetCtlValue((ControlHandle)item, myRefCon);
  455.                 break;
  456.             case statText:
  457.                 if (myRefCon)
  458.                     SetIText(item, (StringPtr)myRefCon);
  459.                 break;
  460.             case editText:
  461.                 SetIText(item, (StringPtr)myRefCon);
  462.                 if(editTextExists == false) {
  463.                     SelIText(dPtr, iNum, 0, 32767);
  464.                     editTextExists = true;
  465.                     }
  466.                 break;
  467.     //        case iconItem:
  468.     //            break;
  469.     //        case picItem:
  470.     //            break;
  471.             case userItem:
  472.                 SetDItem(dPtr, iNum, type, (Handle)myRefCon, &box);
  473.                 break;
  474.             }
  475.         spanPtr++;
  476.         }
  477. #if !defined(FabSystem7orlater)
  478.     if (dialogManager7Present)
  479. #endif
  480.         (void) SetDialogTracksCursor(dPtr, editTextExists);
  481.     if (initProc)
  482.         initProc(dPtr);
  483.     ShowWindow(dPtr);
  484.     
  485. #pragma mark Event Loop
  486.     
  487.     dialoging = true;
  488.     do {
  489.         ModalDialog(filterProc, &theItemHit);
  490.         if (theItemHit) {
  491.             GetDItem(dPtr, theItemHit, &type, &item, &box);
  492.             switch (type) {
  493.                 case ctrlItem+btnCtrl:
  494.                     if ((theItemHit == ok) || (theItemHit == cancel))
  495.                         dialoging = false;
  496.                     else if (userProc)
  497.                         userProc(dPtr, item, theItemHit);
  498.                     break;
  499.                 case ctrlItem+chkCtrl:
  500.                     SetCtlValue((ControlHandle)item, 1 - GetCtlValue((ControlHandle)item));
  501.                     if (userProc)
  502.                         userProc(dPtr, item, theItemHit);
  503.                     break;
  504.                 case ctrlItem+radCtrl:
  505.                     if (GetCtlValue((ControlHandle)item) == 0) {
  506.                         SetCtlValue((ControlHandle)item, 1);
  507.                         for (spanPtr = things; (++spanPtr)->itemNumber != theItemHit; );
  508.                         itemToBeActivated = spanPtr;
  509.                         for (theGroup = spanPtr->group; (--spanPtr)->group == theGroup; );
  510.                         for (; (++spanPtr)->refCon <= 0L; );
  511.                         GetDItem(dPtr, spanPtr->itemNumber, &type, &item, &box);
  512.                         SetCtlValue((ControlHandle)item, 0);
  513.                         spanPtr->refCon = 0L;
  514.                         itemToBeActivated->refCon = 1L;
  515.                         if (userProc)
  516.                             userProc(dPtr, item, theItemHit);
  517.                         }
  518.                     break;
  519.                 case ctrlItem+resCtrl:
  520.                     if (userProc)
  521.                         userProc(dPtr, item, theItemHit);
  522.                     break;
  523.                 }
  524.             }
  525.         }
  526.     while (dialoging);
  527.     
  528. #pragma mark Return Settings
  529.     
  530.     if (theItemHit == ok) {
  531.         spanPtr = things;
  532.         while (iNum = spanPtr->itemNumber) {
  533.             GetDItem(dPtr, iNum, &type, &item, &box);
  534.             theType = type & itemDisable ? type - itemDisable : type;
  535.             switch(theType) {
  536.                 case ctrlItem+chkCtrl:
  537.                 case ctrlItem+resCtrl:
  538.                     spanPtr->refCon = GetCtlValue((ControlHandle)item);
  539.                     break;
  540.                 case editText:
  541.                     GetIText(item, (StringPtr)spanPtr->refCon);
  542.                     break;
  543.         //        case iconItem:
  544.         //            break;
  545.         //        case picItem:
  546.         //            break;
  547.         //        case userItem:
  548.         //            break;
  549.                 }
  550.             spanPtr++;
  551.             }
  552.         }
  553.     DisposeDialog(dPtr);
  554.     SetPort(port);
  555.     }
  556. else
  557.     SysBeep(1);
  558. InitCursor();
  559. return theItemHit;
  560. }
  561.  
  562. /* About box manager */
  563.  
  564. #pragma segment About
  565.  
  566. /* myAbout: the events directed against the about box are checked with
  567. EventAvail, so that we can discard the about box and process
  568. important events later in the main event loop */
  569.  
  570. void myAbout(void (*theIdleProc)(void),
  571.             pascal void (*DrawQTPict)(DialogPtr, short),
  572.             void (*UpdateProc)(EventRecord *),
  573.             void (*ActivateProc)(EventRecord *)
  574.             )
  575. {
  576. EventRecord    evrec;
  577. DialogPtr    agh, dPtr;
  578. short    iHit;
  579. register Handle    splash;
  580. register Boolean    exit = false;
  581.  
  582. splash = OpenSplash(&agh, DrawQTPict);
  583. if (splash) {
  584.     ShowWindow(agh);
  585.     do {
  586.         SystemTask();
  587.         if (EventAvail(everyEvent, &evrec)) {
  588.             switch(evrec.what) {
  589.                 case mouseDown:
  590.                 case keyDown:
  591.                 case autoKey:
  592.                     exit = true;
  593.                     FlushEvents(mDownMask | mUpMask | keyDownMask | autoKeyMask, 0);
  594.                     break;
  595.                 case mouseUp:
  596.                     (void)GetNextEvent(mUpMask, &evrec);
  597.                     break;
  598.                 case updateEvt :
  599.                     (void)GetNextEvent(updateMask, &evrec);
  600.                     if ((DialogPtr)evrec.message == agh) {
  601.                         BeginUpdate(agh);
  602.                         DrawDialog(agh);
  603.                         EndUpdate(agh);
  604.                         }
  605.                     else
  606.                         if (IsDialogEvent(&evrec))
  607.                             (void) DialogSelect(&evrec, &dPtr, &iHit);
  608.                         else
  609.                             UpdateProc(&evrec);
  610.                     break;
  611.                 case diskEvt :
  612.                 case osEvt :
  613.                 case kHighLevelEvent:
  614.                     exit = true;
  615.                     break;
  616.                 case activateEvt :
  617.                     (void)GetNextEvent(activMask, &evrec);
  618.                     if ((DialogPtr)evrec.message != agh) {
  619.                         if (IsDialogEvent(&evrec))
  620.                             (void) DialogSelect(&evrec, &dPtr, &iHit);
  621.                         else
  622.                             ActivateProc(&evrec);
  623.                         }
  624.                     break;
  625.                 }
  626.             }
  627.         else {
  628.             theIdleProc();
  629.             }
  630.         }
  631.     while (exit == false);
  632.     DisposeSplash(splash, agh);
  633.     }
  634. else
  635.     SysBeep(3);
  636. }
  637.  
  638. /* OpenSplash: puts up the about window */
  639.  
  640. Handle OpenSplash(DialogPtr *pass, pascal void (*DrawQTPict)(DialogPtr, short))
  641. {
  642. enum {
  643. kDLOG_About = 256,
  644. kItemPICT = 1
  645. };
  646.  
  647. Str15    tempS = "\p";
  648. Rect    box;
  649. register DialogPtr    dPtr;
  650. register VersRecHndl    myvers;
  651. register Handle    hand;
  652. Handle    item;
  653. short    type;
  654.  
  655. hand = NewHandle(sizeof(DialogRecord));
  656. if (hand) {
  657.     HLockHi(hand);
  658.     myvers = (VersRecHndl)Get1Resource('vers', 1);
  659.     if (myvers) {
  660.         (void) PLstrncpy(tempS, (*myvers)->shortVersion, 15);
  661.         ReleaseResource((Handle)myvers);
  662.         }
  663.     else
  664.         tempS[0] = 0;
  665.     ParamText(&tempS, nil, nil, nil);
  666.     *pass = dPtr = GetNewDialog(kDLOG_About, *hand, (DialogPtr)-1L);
  667.     if (dPtr) {
  668.         if (DrawQTPict) {
  669.             GetDItem(dPtr, kItemPICT, &type, &item, &box);
  670.             SetDItem(dPtr, kItemPICT, type, (Handle)DrawQTPict, &box);
  671.             }
  672.         }
  673.     else {
  674.         DisposHandle(hand);
  675.         hand = nil;
  676.         }
  677.     }
  678. return(hand);
  679. }
  680.  
  681. /* DisposeSplash: gets rid of the about window */
  682.  
  683. void DisposeSplash(Handle dialog, DialogPtr pass)
  684. {
  685. CloseDialog(pass);
  686. DisposHandle(dialog);
  687. }
  688.  
  689. #pragma segment Main
  690.  
  691. /* GetFontNumber: gets font number from font name */
  692.  
  693. Boolean GetFontNumber(ConstStr255Param fontName, short *fontNum)
  694. {
  695. Str255    systemFontName;
  696. register Boolean    retFlag;
  697.  
  698. GetFNum(fontName, fontNum);
  699. if ((retFlag = (*fontNum != 0)) == false) {
  700.     GetFontName(0, systemFontName);
  701.     retFlag = EqualString(fontName, systemFontName, false, false);
  702.     }
  703. return retFlag;
  704. }
  705.  
  706. /*
  707. ** From: dickie@schaefer.math.wisc.edu (Garth Dickie)
  708. ** Newsgroups: comp.sys.mac.programmer
  709. ** Subject: Re: HOW do I get the finder to update its file information..
  710. ** Message-ID: <1992May22.014427.9977@schaefer.math.wisc.edu>
  711. ** Date: 22 May 92 01:44:27 GMT
  712. ** References: <1992May21.231246.23090@crash.cts.com>
  713. ** Organization: Univ. of Wisconsin Dept. of Mathematics
  714. ** Lines: 58
  715. ** 
  716. ** You need to change the modification date of the parent directory.
  717. ** The routine TickleParent below works for me.  In case you are not
  718. ** using the FSSpec structure, the routine MakeWDSpec will convert
  719. ** a working directory / filename pair to a pseudo-FSSpec.  I use
  720. ** this when the new file manager calls are not available, as the rest
  721. ** of my code passes around FSSpecs.  The code compiles under THINK C
  722. ** 5.0, with the usual headers.
  723. ** 
  724. ** BTW (mild flame) this is simple enough that it's pretty annoying
  725. ** when people don't do it.  Most of the nifty little 'drag-and-drop'
  726. ** utilities that have come around recently forget to do this.  Feel
  727. ** free to use the code below in any way you see fit.
  728. */
  729.  
  730. OSErr TickleParent( FSSpec *child )
  731. {
  732. CInfoPBRec    pb;
  733. OSErr         err;
  734.  
  735. pb.dirInfo.ioCompletion = nil;
  736. pb.dirInfo.ioNamePtr = nil;
  737. pb.dirInfo.ioVRefNum = child->vRefNum;
  738. pb.dirInfo.ioFDirIndex = -1;
  739. pb.dirInfo.ioDrDirID = child->parID;
  740.  
  741. err = PBGetCatInfoSync( &pb );
  742.  
  743. if (err == noErr) {
  744.     GetDateTime( &pb.dirInfo.ioDrMdDat );
  745.     pb.dirInfo.ioFDirIndex = 0;
  746. //    pb.dirInfo.ioNamePtr = &child->name;
  747.     pb.dirInfo.ioDrDirID = child->parID;
  748.     err = PBSetCatInfoSync( &pb );
  749.     }
  750.  
  751. return err;
  752. }
  753.  
  754. /* this is taken from "Macintosh Programming Secrets"
  755. by Scott Knaster & Keith Rollin;
  756. optimization by Fabrizio Oddone */
  757.  
  758. Boolean CmdPeriod(EventRecord *theEvent)
  759. {
  760. #define    kModifiersMask    (0xFF00 & ~cmdKey)
  761.  
  762. Handle    hKCHR;
  763. long    /*virtualKey, */keyInfo, state, keyCID;
  764. short    keyCode;
  765. Boolean    result = false;
  766.  
  767. if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
  768.     if (theEvent->modifiers & cmdKey) {
  769. //        virtualKey = (theEvent->message >> 8) >> 8;
  770.         keyCode = (theEvent->modifiers & kModifiersMask) | ((unsigned short)theEvent->message >> 8);
  771.         state = 0;
  772.         keyCID = GetScript(GetEnvirons(smKeyScript), smScriptKeys);
  773.         hKCHR = GetResource('KCHR', keyCID);
  774.         if (hKCHR) {
  775.             keyInfo = KeyTrans(*hKCHR, keyCode, &state);
  776.             ReleaseResource(hKCHR);
  777.             }
  778.         else
  779.             keyInfo = theEvent->message;
  780.         
  781.         if (((char)keyInfo == '.') || ((char)(keyInfo >> 16) == '.'))
  782.             result = true;
  783.         }
  784.     }
  785.  
  786. return result;
  787. }
  788.  
  789. /* other useful stuff to detect keypresses */
  790.  
  791. Boolean CmdPeriodOrEsc(EventRecord *theEvent)
  792. {
  793. return ((unsigned short)theEvent->message == kEscapeKey) || CmdPeriod(theEvent);
  794. }
  795.  
  796. Boolean CmdPeriodOrEscConfirm(EventRecord *theEvent, short alertID, ModalFilterProcPtr filterProc)
  797. {
  798. register Boolean    retflag;
  799.  
  800. retflag = CmdPeriodOrEsc(theEvent);
  801. if (retflag) {
  802.     InitCursor();
  803.     retflag = CautionAlert(alertID, filterProc) == cancel;
  804.     }
  805.  
  806. return retflag;
  807. }
  808.  
  809. #pragma segment Registration
  810.  
  811. Str255    regInfo[13] = { "\p", "\p", "\p", "\p", "\p", "\p", "\p", "\p", "\p", "\p", "\p", "\p", "\p" };
  812. short gHowManyDollars;
  813.  
  814. void HandleRegistration(ModalFilterProcPtr filterProc,
  815.                         long (*regCfgInfo)(Handle, long, StringPtr),
  816.                         short howManyDollars)
  817. {
  818. enum {
  819. kMyRegText = 256
  820. };
  821.  
  822. StdFileResult    theChosenFile;
  823. ParamBlockRec    myPB;
  824. EventRecord    dummyEv;
  825. Str63    tempS = "\p";
  826. long    gResp;
  827. short    tmpFRefN;
  828. const short    zero = 0x0130;
  829. const short    dash = 0x012D;
  830. const char    optspace = 'Δ';
  831. Handle    regText;
  832. VersRecHndl    myvers;
  833. StringHandle    sh;
  834. StringPtr    myAppName = nil;
  835. long    lOffset;
  836. short    i;
  837. OSErr    err;
  838. SignedByte    savedState;
  839.  
  840. dialogItems    things[] = {{ ok, 0, 0L },
  841.                         { cancel, 0, 0L },
  842.                         { kItemUserName, 0, (long)®Info[0] },
  843.                         { kItemCompany, 0, (long)®Info[1] },
  844.                         { kItemAddress, 0, (long)®Info[2] },
  845.                         { kItemCity, 0, (long)®Info[3] },
  846.                         { kItemState, 0, (long)®Info[4] },
  847.                         { kItemZIP, 0, (long)®Info[5] },
  848.                         { kItemCountry, 0, (long)®Info[6] },
  849.                         { kItemE_mail, 0, (long)®Info[7] },
  850.                         { kItemPhone, 0, (long)®Info[8] },
  851.                         { kItemFAX, 0, (long)®Info[9] },
  852.                         { kItemQuantity, 0, (long)®Info[12] },
  853.                         { kItemCopyFrom, 0, (long)®Info[10] },
  854.                         { kItemComments, 0, (long)®Info[11] },
  855.                         { 0, 0, 0L}
  856.                         };
  857.  
  858. gHowManyDollars = howManyDollars;
  859. sh = GetString(kSTR_ApplicationName);
  860. if (sh) {
  861.     savedState = WantThisHandleSafe(sh);
  862.     myAppName = *sh;
  863.     }
  864.  
  865. ParamText(myAppName, (ConstStr255Param)&zero, (ConstStr255Param)&zero, nil);
  866. if (sh)
  867.     HSetState(sh, savedState);
  868. if (HandleDialog(filterProc, &things, RegInitProc, nil, kDLOG_Register) == ok) {
  869.     do {
  870.         if ((err = AskForDestFile(&theChosenFile)) == dupFNErr) {
  871.             InitCursor();
  872.             (void)StopAlert(kALRT_REGCANNOTREPLACE, nil);
  873.             }
  874.         }
  875.     while (err == dupFNErr);
  876.     if (err == noErr) {
  877.         regText = Get1Resource('TEXT', kMyRegText);
  878.         if (regText) {
  879.             DetachResource(regText);
  880.             myvers = (VersRecHndl)Get1Resource('vers', 1);
  881.             if (myvers) {
  882.                 (void) PLstrcpy(tempS, (*myvers)->shortVersion);
  883.                 ReleaseResource((Handle)myvers);
  884.                 }
  885.             lOffset = Munger(regText, 0L, &optspace, 1L, &tempS[1], tempS[0]);
  886.             for (i = 0; i <= 11; i++)
  887.                 lOffset = Munger(regText, lOffset, &optspace, 1L, ®Info[i][1], regInfo[i][0]);
  888.             
  889.             /* Mac model */
  890.             if (Gestalt(gestaltMachineType, &gResp) == noErr) {
  891.                 myAppName = GetPtrIndHString(GetResource('STR#', kMachineNameStrID), gResp - 1);
  892.                 lOffset = Munger(regText, lOffset, &optspace, 1L, &myAppName[1], myAppName[0]);
  893.                 }
  894.             else {
  895.                 lOffset = Munger(regText, lOffset, &optspace, 1L, &((char *)&dash)[1], 1L);
  896.                 }
  897.             /* Sys version */
  898.             if (Gestalt(gestaltSystemVersion, &gResp) == noErr) {
  899.                 BCDVersNumToString(gResp, tempS);
  900.                 }
  901.             else {
  902.                 *(short *)tempS = dash;
  903.                 }
  904.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  905.             /* addr mode info */
  906.             if (Gestalt(gestaltAddressingModeAttr, &gResp) == noErr) {
  907.                 MyNumToString(gResp, tempS);
  908.                 }
  909.             else {
  910.                 *(short *)tempS = dash;
  911.                 }
  912.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  913.             /* A/UX info */
  914.             if (Gestalt(gestaltAUXVersion, &gResp) == noErr) {
  915.                 BCDVersNumToString(gResp, tempS);
  916.                 }
  917.             else {
  918.                 *(short *)tempS = dash;
  919.                 }
  920.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  921.             /* Hardware info */
  922.             if (Gestalt(gestaltHardwareAttr, &gResp) == noErr) {
  923.                 MyNumToString(gResp, tempS);
  924.                 }
  925.             else {
  926.                 *(short *)tempS = dash;
  927.                 }
  928.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  929.             /* VM info */
  930.             if (Gestalt(gestaltVMAttr, &gResp) == noErr) {
  931.                 MyNumToString(gResp, tempS);
  932.                 }
  933.             else {
  934.                 *(short *)tempS = dash;
  935.                 }
  936.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  937.             /* Power Manager info */
  938.             if (Gestalt(gestaltPowerMgrAttr, &gResp) == noErr) {
  939.                 MyNumToString(gResp, tempS);
  940.                 }
  941.             else {
  942.                 *(short *)tempS = dash;
  943.                 }
  944.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  945.             /* Processor type info */
  946.             if (Gestalt(gestaltProcessorType, &gResp) == noErr) {
  947.                 MyNumToString(gResp, tempS);
  948.                 }
  949.             else {
  950.                 *(short *)tempS = dash;
  951.                 }
  952.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  953.             /* System architecture info */
  954.             if (Gestalt('sysa', &gResp) == noErr) {
  955.                 MyNumToString(gResp, tempS);
  956.                 }
  957.             else {
  958.                 *(short *)tempS = dash;
  959.                 }
  960.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  961.             /* Native processor info */
  962.             if (Gestalt('cput', &gResp) == noErr) {
  963.                 MyNumToString(gResp, tempS);
  964.                 }
  965.             else {
  966.                 *(short *)tempS = dash;
  967.                 }
  968.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  969.             /* System 7 tuner info */
  970.             if (Gestalt('bugz', &gResp) == noErr) {
  971.                 MyNumToString(gResp, tempS);
  972.                 }
  973.             else {
  974.                 *(short *)tempS = dash;
  975.                 }
  976.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  977.             /* Hardware System Updater info */
  978.             if (Gestalt('bugy', &gResp) == noErr) {
  979.                 MyNumToString(gResp, tempS);
  980.                 }
  981.             else {
  982.                 *(short *)tempS = dash;
  983.                 }
  984.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  985.             /* AppleScript info */
  986.             if (Gestalt('ascv', &gResp) == noErr) {
  987.                 BCDVersNumToString(gResp, tempS);
  988.                 }
  989.             else {
  990.                 *(short *)tempS = dash;
  991.                 }
  992.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  993.             /* QuickTime info */
  994.             if (Gestalt('qtim', &gResp) == noErr) {
  995.                 BCDLongVersNumToString(gResp, tempS);
  996.                 }
  997.             else {
  998.                 *(short *)tempS = dash;
  999.                 }
  1000.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  1001.             /* Thread Manager info */
  1002.             if (Gestalt(gestaltThreadMgrAttr, &gResp) == noErr) {
  1003.                 MyNumToString(gResp, tempS);
  1004.                 }
  1005.             else {
  1006.                 *(short *)tempS = dash;
  1007.                 }
  1008.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  1009.             /* custom configuration */
  1010.             if (regCfgInfo)
  1011.                 lOffset = regCfgInfo(regText, lOffset, tempS);
  1012.             
  1013.             /* quantity */
  1014.             lOffset = Munger(regText, lOffset, &optspace, 1L, ®Info[12][1], regInfo[12][0]);
  1015.             MyNumToString(howManyDollars * power(MyStringToNum(regInfo[12]), 0.5), tempS);
  1016.             UnloadSeg(pow);
  1017.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  1018.             IUDateString(*(long *)TimeLM, longDate, tempS);
  1019.             lOffset = Munger(regText, lOffset, &optspace, 1L, &tempS[1], tempS[0]);
  1020. // 6
  1021.             if ((err = FabFSpCreate(&theChosenFile.destFile, 'ttxt', 'TEXT', theChosenFile.theScript)) == noErr) {
  1022.                 if ((err = FabFSpOpenDF(&theChosenFile.destFile, fsWrPerm, &tmpFRefN)) == noErr) {
  1023. // 6
  1024.                     HLockHi(regText);
  1025.                     myPB.ioParam.ioCompletion = nil;
  1026.                     myPB.ioParam.ioBuffer = *regText;
  1027.                     myPB.ioParam.ioReqCount = GetHandleSize(regText);
  1028.                     myPB.ioParam.ioPosMode = fsFromStart;
  1029.                     myPB.ioParam.ioRefNum = tmpFRefN;
  1030.                     myPB.ioParam.ioPosOffset = 0L;
  1031.                     (void)PBWriteAsync(&myPB);
  1032.                     while (myPB.ioParam.ioResult > 0) {
  1033.                         SystemTask();
  1034.                         (void)EventAvail(everyEvent, &dummyEv);
  1035.                         }
  1036.                     HUnlock(regText);
  1037.                     (void)FSClose(tmpFRefN);
  1038.                     InitCursor();
  1039.                     MyNumToString(myPB.ioParam.ioResult, tempS);
  1040.                     ParamText(theChosenFile.destFile.name, tempS, nil, nil);
  1041.                     if (myPB.ioParam.ioResult == noErr) {
  1042.                         (void) NoteAlert(kALRT_REGSUCCESSSAVED, nil);
  1043.                         }
  1044.                     else if (myPB.ioParam.ioResult == dskFulErr) {
  1045. // 6
  1046.                         (void) FabFSpDelete(&theChosenFile.destFile);
  1047. // 6
  1048.                         (void) StopAlert(kALRT_REGDISKFULL, nil);
  1049.                         }
  1050.                     else
  1051.                         (void) StopAlert(kALRT_REGUNKNOWNWRITEERROR, nil);
  1052.                     }
  1053.                 else
  1054.                     (void) StopAlert(kALRT_REGCOULDNOTOPENFORWRITING, nil);
  1055.                 }
  1056.             else
  1057.                 (void) StopAlert(kALRT_REGCOULDNOTCREATE, nil);
  1058.             DisposHandle(regText);
  1059.             }
  1060.         }
  1061.     }
  1062. }
  1063.  
  1064. void RegInitProc(DialogPtr myDPtr)
  1065. {
  1066. Str255    textStr, discountStr;
  1067. Rect    iRect;
  1068. Handle    iHandle;
  1069. long    qty;
  1070. short    iType;
  1071. register RgnHandle    updtRgn;
  1072.  
  1073. GetDItem(myDPtr, kItemQuantity, &iType, &iHandle, &iRect);
  1074. GetIText(iHandle, textStr);
  1075. qty = MyStringToNum(textStr);
  1076. MyNumToString(gHowManyDollars * qty, textStr);
  1077. MyNumToString(gHowManyDollars * power(qty, 0.5), discountStr);
  1078. UnloadSeg(pow);
  1079. ParamText(nil, textStr, discountStr, nil);
  1080. GetDItem(myDPtr, kItemTotals, &iType, &iHandle, &iRect);
  1081. updtRgn = NewRgn();
  1082. if (updtRgn) {
  1083.     RectRgn(updtRgn, &iRect);
  1084.     UpdtDialog(myDPtr, updtRgn);
  1085.     DisposeRgn(updtRgn);
  1086.     }
  1087. }
  1088.  
  1089. OSErr AskForDestFile(StdFileResultPtr whichFile)
  1090. {
  1091. enum {
  1092. kSTR_PROMPT = 300,
  1093. kSTR_DEFNAME
  1094. };
  1095.  
  1096. StandardFileReply    mySFR;
  1097. register Handle    sH1 = (Handle)GetString(kSTR_PROMPT);
  1098. register Handle    sH2 = (Handle)GetString(kSTR_DEFNAME);
  1099. register SignedByte    state1, state2;
  1100. register OSErr    err = userCanceledErr;
  1101.  
  1102. state1 = WantThisHandleSafe(sH1);
  1103. state2 = WantThisHandleSafe(sH2);
  1104. // 6
  1105. FabStandardPutFile(*sH1, *sH2, &mySFR);
  1106. // 6
  1107. HSetState(sH2, state2);
  1108. HSetState(sH1, state1);
  1109. if (mySFR.sfGood) {
  1110.     if (mySFR.sfReplacing)
  1111.         err = dupFNErr;
  1112.     else {
  1113.         err = noErr;
  1114.         whichFile->destFile = mySFR.sfFile;
  1115.         whichFile->theScript = mySFR.sfScript;
  1116.         }
  1117.     }
  1118. return err;
  1119. }
  1120.  
  1121. void BCDVersNumToString(long num, StringPtr str)
  1122. {
  1123. Str15    tmpstr;
  1124. const short    onepoint = 0x012E;
  1125. register long    tmp;
  1126.  
  1127. str[0] = 0;
  1128. tmp = num;
  1129. tmp >>= 8;
  1130. tmp &= 0xFF;
  1131. MyNumToString(tmp, str);
  1132. (void) PLstrcat(str, (StringPtr)&onepoint);
  1133. tmp = num;
  1134. tmp >>= 4;
  1135. tmp &= 0xF;
  1136. MyNumToString(tmp, tmpstr);
  1137. (void) PLstrcat(str, &tmpstr);
  1138. tmp = num;
  1139. tmp &= 0xF;
  1140. if (tmp) {
  1141.     MyNumToString(tmp, tmpstr);
  1142.     (void) PLstrcat(str, (StringPtr)&onepoint);
  1143.     (void) PLstrcat(str, &tmpstr);
  1144.     }
  1145. }
  1146.  
  1147. void BCDLongVersNumToString(long num, StringPtr str)
  1148. {
  1149. Str15    tmpstr;
  1150. const short    onepoint = 0x012E;
  1151. const short    devStr = 0x0164;
  1152. const short    alphaStr = 0x0161;
  1153. const short    betaStr = 0x0162;
  1154. const short    releaseStr = 0x0172;
  1155. register long    tmp;
  1156.  
  1157. str[0] = 0;
  1158. tmp = num;
  1159. tmp >>= 24;
  1160. tmp &= 0xFF;
  1161. MyNumToString(tmp, str);
  1162. (void) PLstrcat(str, (StringPtr)&onepoint);
  1163. tmp = num;
  1164. tmp >>= 20;
  1165. tmp &= 0xF;
  1166. MyNumToString(tmp, tmpstr);
  1167. (void) PLstrcat(str, &tmpstr);
  1168. tmp = num;
  1169. tmp >>= 16;
  1170. tmp &= 0xF;
  1171. if (tmp) {
  1172.     MyNumToString(tmp, tmpstr);
  1173.     (void) PLstrcat(str, (StringPtr)&onepoint);
  1174.     (void) PLstrcat(str, &tmpstr);
  1175.     }
  1176. tmp = num;
  1177. tmp >>= 8;
  1178. tmp &= 0xFF;
  1179. switch (tmp) {
  1180.     case developStage:
  1181.         (void) PLstrcat(str, (StringPtr)&devStr);
  1182.         break;
  1183.     case alphaStage:
  1184.         (void) PLstrcat(str, (StringPtr)&alphaStr);
  1185.         break;
  1186.     case betaStage:
  1187.         (void) PLstrcat(str, (StringPtr)&betaStr);
  1188.         break;
  1189.     case finalStage:
  1190.         (void) PLstrcat(str, (StringPtr)&releaseStr);
  1191.         break;
  1192.     }
  1193. tmp = num;
  1194. tmp &= 0xFF;
  1195. if (tmp) {
  1196.     MyNumToString(tmp, tmpstr);
  1197.     (void) PLstrcat(str, &tmpstr);
  1198.     }
  1199. }
  1200.  
  1201. #pragma segment Init
  1202.  
  1203. /* Code from Apple® converted by Fabrizio Oddone in super-optimized (!) C */
  1204.  
  1205. /* InitGraf is always implemented (trap $A86E). If the trap table is big
  1206.   enough, trap $AA6E will always point to either Unimplemented or some other
  1207.   trap, but will never be the same as InitGraf. Thus, you can check the size
  1208.   of the trap table by asking if the address of trap $A86E is the same as
  1209.   $AA6E. */
  1210.  
  1211. #define NumToolboxTraps    ((NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap)) ? 0x0200 : 0x0400)
  1212.  
  1213. /* Determines the type of a trap based on its trap number. If bit 11 is clear,
  1214.   then it is an OS trap. Otherwise, it is a Toolbox trap. */
  1215. /* OS traps start with A0, Tool with A8 or AA. */
  1216.  
  1217. #define GetTrapType(which)    (((which) & 0x0800) ? ToolTrap : OSTrap)
  1218.  
  1219. /* Check to see if a given trap is implemented. This is only used by the
  1220.   Initialize routine in this program, so we put it in the Initialize segment.*/
  1221.  
  1222. Boolean TrapAvailable(short theTrap)
  1223. {
  1224. TrapType    theTrapType;
  1225. register short    temp;
  1226.  
  1227. temp = theTrap;
  1228. if((theTrapType = GetTrapType(temp)) == ToolTrap) {
  1229.     temp &= 0x07FF;
  1230.     if( temp >= NumToolboxTraps)
  1231.         temp = _Unimplemented;
  1232.     }
  1233. return( NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(temp,
  1234.                   theTrapType));
  1235. }
  1236.  
  1237.